Thread: how to understand '|=' and '<<'

  1. #1
    Registered User
    Join Date
    Dec 2014
    Posts
    3

    how to understand '|=' and '<<'

    Hi all, I am a very beginner of C. There is a code which I cannot purely understand how does the MirrorBytes() function run.

    there is the code:
    Code:
    function1(unsigned char *inBlock, unsigned char *outBlock,)
    {
    unsigned int left = MirrorBytes (((unsigned int *)inBlock)[0]);
    unsigned int right = MirrorBytes (((unsigned int *)inBlock)[1]);
    ...
    ...
    }
    
    unsigned int MirrorBytes (unsigned int x)
    {
    unsigned int n = (unsigned char) x;
    n<<=8; n|=(unsigned char) (x >>8);
    n<<=8; n|=(unsigned char) (x>>16);
    return (n<<8) | (unsigned char) (x>>24);
    }
    For example: if the value of the inBlock is '11010111', how does the MirrorBytes() function run?
    if the value of the inBlock is '1101011101000110', how does the MirrorBytes() function run?

    Thank you very much!!

  2. #2
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,127
    Quote Originally Posted by xnigel View Post
    Hi all, I am a very beginner of C. There is a code which I cannot purely understand how does the MirrorBytes() function run.

    there is the code:
    Code:
    function1(unsigned char *inBlock, unsigned char *outBlock,)
    {
    unsigned int left = MirrorBytes (((unsigned int *)inBlock)[0]);
    unsigned int right = MirrorBytes (((unsigned int *)inBlock)[1]);
    ...
    ...
    }
    
    unsigned int MirrorBytes (unsigned int x)
    {
    unsigned int n = (unsigned char) x;
    n<<=8; n|=(unsigned char) (x >>8);
    n<<=8; n|=(unsigned char) (x>>16);
    return (n<<8) | (unsigned char) (x>>24);
    }
    For example: if the value of the inBlock is '11010111', how does the MirrorBytes() function run?
    if the value of the inBlock is '1101011101000110', how does the MirrorBytes() function run?

    Thank you very much!!
    This code assumes a 32 bit, (4 byte) unsigned int. The function will reverse the order of the bytes.

    If the original byte order is 1234 then the result byte order would be 4321.

    It basically converts Bid-Endian, into Little-Endin, and vice-versa

  3. #3
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    '|' is the bitwise OR operator.

    Code:
    /*
        Truth Table for OR
    
        false OR false = false   |  '0' OR '0' = '0'
        false OR true  = true    |  '0' OR '1' = '1'
        true  OR false = true    |  '1' OR '0' = '1'
        true  OR true  = true    |  '1' OR '1' = '1'
    */
    The above table shows the OR logic for a single bit. Notice how the output is only false (zero) when both [all] inputs are false (zero).

    To perform a bitwise OR between two binary values by hand, write them down one over the other, and apply the truth table to each bit position (column).

    Here's an example with two four-bit numbers:

    Code:
    /*
        value 1:  0110   <---> 0x6
        value 2:  1010   <---> 0xA
                  ----
    
      // 1st column: compares zero and zero, so the result for that position is zero
    
        value 1:  0110   <---> 0x6
        value 2:  1010   <---> 0xA
                  ----
                     0
    
      // 2nd column: compares one and one, so the result for that position is one
    
        value 1:  0110   <---> 0x6
        value 2:  1010   <---> 0xA
                  ----
                    10
    
      // 3rd column: compares one and zero, so the result for that position is one
    
        value 1:  0110   <---> 0x6
        value 2:  1010   <---> 0xA
                  ----
                   110
    
      // 4th column: compares zero and one, so the result for that position is one
    
        value 1:  0110   <---> 0x6
        value 2:  1010   <---> 0xA
                  ----
                  1110   <---> 0xE
    */
    As far as the '|=', this is simply the short-hand assignment operator for bitwise OR. It stores the result back into the variable on the left side.




    '<<' is a bitwise left shift operator. It shifts the value on the left, to the left, a number of places indicated by the value on the right. This should be covered in any basic C programming book. You can also find more information on operators on the net; e.g. here: Operators in C and C++ - Wikipedia, the free encyclopedia

    Note that the code you provided also uses '<<=', which, as above, includes an assignment operator with the shift.



    Now, with all of that, you should be able to follow the code and see exactly what it is doing.

    Grab a pen and paper and sit down with the function. Write an initial value for each variable. Step through the code, by hand, updating the value of each variable based on the code. One line of code might require several steps by hand (e.g. my example with two four-bit numbers above). But this should give you a solid understanding of exactly what the function is doing, as well as some basic logic exercise.
    Last edited by Matticus; 12-10-2014 at 10:14 AM.

  4. #4
    Registered User
    Join Date
    Dec 2014
    Posts
    3
    Hi Rstanley and Matticus,

    Thank both of you I think I have got something. Take a example for good practice: x = 0xACDB4213
    Code:
    firstly, if do n<<=8; n will be 0xDB421300, then n=n|(x>>8). That is n = 0xDB421300 | 0x00ACDB42. n = 0xDBEEDB42
    secondly, do another n<<=8; n will be 0xEEDB4200, then n = 0xEEDB4200 | 0x0000ACDB. n = 0xEEDBEEDB
    finally, n is 0xDBEEDB00, n = 0xDBEEDB00 | 0x 000000AC. n = 0xDBEEDBAC
    According to your answer, the 'real' result should be 0x1342CDAB. So there must be somewhere I did wrong. Could you please correct me?

  5. #5
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,127
    Quote Originally Posted by xnigel View Post
    Hi Rstanley and Matticus,

    Thank both of you I think I have got something. Take a example for good practice: x = 0xACDB4213
    Code:
    firstly, if do n<<=8; n will be 0xDB421300, then n=n|(x>>8). That is n = 0xDB421300 | 0x00ACDB42. n = 0xDBEEDB42
    secondly, do another n<<=8; n will be 0xEEDB4200, then n = 0xEEDB4200 | 0x0000ACDB. n = 0xEEDBEEDB
    finally, n is 0xDBEEDB00, n = 0xDBEEDB00 | 0x 000000AC. n = 0xDBEEDBAC
    According to your answer, the 'real' result should be 0x1342CDAB. So there must be somewhere I did wrong. Could you please correct me?
    You will need to post the full CURRENT code so we can examine.

    Thank you.

  6. #6
    Registered User
    Join Date
    Dec 2014
    Posts
    3
    Hi all, this afternoon i wrote a code and run in the Geany program though i do not have the full code. I just want work out why the result i calculated was not correct. The code written in the program is:
    Code:
    #include <stdio.h>
    unsigned int n;
    unsigned int m, m1, m2, m3, m4, m5, m6;
    unsigned int z1, z2, z3, z4, z5, z6;
    
    unsigned int MB32(unsigned int x)
    {
    	n = (unsigned char) x; // get last char of x, n == 'cd'.
    	m = (unsigned char) x;
    	
    	n <<= 8;	// n == 'cd00'
    	
    	m1 = n;		// 
    	z1 = x;		// z1 == x == '12 34 ab cd'
    	
    	n |= (unsigned char) (x >> 8);
    	
    	m2 = n;		//display the 1st result of n;
    	z2 = x;		//display the 1st result of x;
    	
    	//=================================================
    	
    	n <<= 8;
    	
    	m3 = n;
    	z3 = x;
    		
    	n |= (unsigned char) (x >> 16);
    	
    	m4 = n;
    	z4 = x;
    	
    	//=================================================
    
    	//return (n << 8) | (unsigned char) (x >> 24);
    	n <<= 8;
    	
    	m5 = n;
    	z5 = x;
    	
    	n |= (unsigned char) (x >> 24);
    	
    	m6 = n;
    	z6 = x;
    	
    	return n;
    }
    
    int main()
    {
    	
    	//int BlockIn = 0xABCD1234;
    	int BlockIn = 0x1234ABCD;
    	int BlockOut = MB32(BlockIn);
    	printf ("BlockIn is: %x \n", BlockIn);
    	printf ("BlockOut is: %x \n", BlockOut);
    	printf ("m  = %x \n", m);
    	printf ("m1 = %x \n", m1);
    	printf ("z1 = %x \n \n", z1);
    	printf ("m2 = %x \n", m2);
    	printf ("z2 = %x \n \n", z2);
    	printf ("m3 = %x \n", m3);
    	printf ("z3 = %x \n \n", z3);
    	printf ("m4 = %x \n", m4);
    	printf ("z4 = %x \n \n", z4);
    	printf ("m5 = %x \n", m5);
    	printf ("z5 = %x \n \n", z5);
    	printf ("m6 = %x \n", m6);
    	printf ("z6 = %x \n \n", z6);
    
    	return 0;
    }


    I think only the reason i got the wrong answer is because of the definition of 'unsigned char x', 'unsigned int x', and 'unsigned int n'. Some comment were added. I wish this can be used for other learner as well. This could could be run under 64bit Ubuntu.

    Thank you all guys!

  7. #7
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,127
    I think only the reason i got the wrong answer is because of the definition of 'unsigned char x', 'unsigned int x', and 'unsigned int n'.
    What "wrong answer" did you get?

    When I run your code with "1234abcd" as the input, the output is, "cdab3412".

    Is this not the correct output? If not, what output did you expect?

    BTW:
    Code:
    int main()
    
    should be:
    
    int main(void)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I don't understand how to do this please help T_T
    By Chester Cardano in forum C++ Programming
    Replies: 5
    Last Post: 08-01-2013, 11:44 AM
  2. plz help me understand this
    By Farnaz in forum C# Programming
    Replies: 3
    Last Post: 07-06-2011, 11:15 AM
  3. please help me understand this
    By litzkrieg in forum C Programming
    Replies: 8
    Last Post: 02-16-2011, 01:44 PM
  4. help me understand...
    By stormfront in forum C Programming
    Replies: 2
    Last Post: 10-12-2005, 10:47 AM
  5. Help me out understand what I need to do please?
    By seal in forum C Programming
    Replies: 8
    Last Post: 10-11-2005, 10:31 PM

Tags for this Thread